#include "palmvein_com.h"
#include "palmvein_protocol.h"

#define DEBUG_EN

#if defined(PALMVEIN_DEBUG)
#define PALMVEIN_COM_TASK_DEBUG_LOG(format, ...) OSAL_LOG(C_LIGHT_CYAN format C_NONE, ##__VA_ARGS__)
#define __PALMVEIN_COM_TASK_DEBUG_LOG(format, ...) __OSAL_LOG(C_LIGHT_CYAN format C_NONE, ##__VA_ARGS__)
#else
#define PALMVEIN_COM_TASK_DEBUG_LOG(format, ...)
#define __PALMVEIN_COM_TASK_DEBUG_LOG(format, ...) __OSAL_LOG(C_YELLOW format C_NONE, ##__VA_ARGS__)
#endif

#define PALMVEIN_COM_TASK_LOG(format, ...) OSAL_LOG(C_LIGHT_CYAN format C_NONE, ##__VA_ARGS__)
#define __PALMVEIN_COM_TASK_LOG(format, ...) __OSAL_LOG(C_LIGHT_CYAN format C_NONE, ##__VA_ARGS__)


#define PROTOCOL_STX                0xEFAA //帧数据头
#define PACK_TYPE_CONFRIM           0X00 //应答包类型：确认包
#define PACK_TYPE_ACK               0X01	   //应答包类型：应答包
/*功能函数宏定义*/
#define CHECK_SUM_DATA_START        2          //校验和计算起始字节相对帧首字节偏移
#define CHECK_SUN_LEN_ADD           3	            //校验和计算长度相对帧长度增加的个数

#define MAX_TX_PACKAGE_LEN            1088          //最大包长
#define MAX_RX_PACKAGE_LEN            128          //最大包长

/* virtual hardware interpalmvein */
#define VHW_PIN_PALMVEIN_POWER      vPIN_C30
#define VHW_UART_PALMVEIN           vUART_11

/* palmvein power control */
#define PALMVEIN_MODULE_POWER_ON    Device_Write(VHW_PIN_PALMVEIN_POWER, NULL, 0, 1)
#define PALMVEIN_MODULE_POWER_OFF   Device_Write(VHW_PIN_PALMVEIN_POWER, NULL, 0, 0)

static RingBufferHandle_t palmveinTx_rbHandle = NULL;          /* 发送循环队列句柄 */
static RingBufferHandle_t palmveinRx_rbHandle = NULL;		    /* 串口接收数据的队列句柄 */


/* 回调函数 */
static PalmVeinMessageCallback_fun_t pCmdCallback = NULL;



Palmvein_Status_stu_t palmveinModuleStatus //掌静脉模组状态
    = {
		.curStatus = PALMVEIN_STATUS_POWER_DOWN,	 //掌静脉模组当前状态
		.curMode = PALMVEIN_MODULE_SLEEPED_MODE, //掌静脉模组当前的工作模式
		.allowBreakIn = ALLOW,
		.timeout = FOREVER_TIME_OUT,
};


/*********************************************************************************************/
/************************************发送和接收数据结构体定义START***************************************/

#pragma pack(1)
/*帧头数据结构*/
typedef struct
{
	uint16_t stx;  //帧头同步字
	uint8_t msgID; //消息ID
	uint16_t len;  //data数据长度
} ProtocolDataHead_stu_t;

/*加密帧头数据结构*/
typedef struct
{
	uint16_t stx;	//帧头同步字
	uint16_t len;	//data数据长度
	uint8_t data[]; //命令
} ProtocolDataHeadEncrypt_stu_t;

/*帧数据结构*/
typedef struct
{
	ProtocolDataHead_stu_t head; //帧头结构体
	uint8_t data[];				 //命令
} CmdPacket_stu_t;

/*M:模组
 *H:主控*/
/*M->H reply 模块对主控的应答data结构解析 msgID为0x00*/
typedef struct
{
	uint8_t r_msgID;  //应答对应的消息ID和命令的msg_ID 对应
	uint8_t result;	  //应答结果
	uint8_t r_data[]; //应答数据缓存
} Reply_data_stu_t;

/*note数据的结构*/
typedef struct
{
	uint8_t n_msgID;  //note ID
	uint8_t n_data[]; //note 数据缓存
} Note_data_stu_t;
#pragma pack()

//发送包信息
static struct
{
	uint8_t dataBuf[MAX_TX_PACKAGE_LEN];      //当前发送的整包数据
	uint16_t dataLen;		//当前发送数据的总长度

	uint8_t cmd;			 //msgid
	uint8_t cnt;			 //
	FlagStatus waitAckFlag;	 //等待ack标志位
	uint32_t timeStamp;		 //时间戳
	uint32_t waitAckTimeout; //等待超时时间
	enum
	{					 
		TX_STA_IDLE,	  
		TX_STA_WAIT_ACK, 
        TX_STA_WAIT_NEXT
	} status;
} CmdPacketTxInfo;

//接收包信息
static struct
{
	uint8_t protocolBuf[MAX_RX_PACKAGE_LEN]; 	//协议buff
	uint8_t protocolCount;				  		//协议计数
} CmdPacketRxInfo;
/*************************************发送和接收数据结构体定义END**************************************/


/**
  * @brief  故障处理
  * @note
  * @param  err：是否故障
  * @return void
  */
void palmvein_err_process(uint8_t err)
{
	static uint8_t err_flag = 0xff;
    if (err != err_flag)
    {
        err_flag = err;
        OSAL_MessagePublishErrorCode(ERRCODE_TYPE_PALMVEIN, err_flag);
    }
}


/****************************************************************************************************/
/*************************************发送操作相关函数 START******************************************/

/**
  * @brief  打印数据
  * @note
  *
  * @param  pData: 数据指针
  * @param  len: 数据长度
  * @return 
  * 
  * 
  */
static void PalmveinCom_PrintfTxData(uint8_t *pData, uint16_t len)
{
#if defined(DEBUG_EN)
	uint8_t strBuffer[66 * 3], i;
	if (len > 65)
		return; //格式化数组数量不能超过66*3
	for (i = 0; i < len; i++)
	{
		sprintf((char *)&strBuffer[i * 3], "%02X ", pData[i]);
	}
	sprintf((char *)&strBuffer[i * 3], "%s", "\r\n\r\n");
	PALMVEIN_COM_TASK_LOG("PalmveinTask send packet:%s", strBuffer);
#endif
}

/**
  * @brief  校验和
  * @note
  *
  * @param  pData: 数据指针
  * @param  len: 数据长度
  * @return 数据异或校验和:
  * 		非加密数据：除帧头（EF AA）和最后一个校验和以外的所有字节都需要计算
  * 		加密数据：除帧头（EF AA）、 长度（从0开始算，第2、3个字节）和最后一个校验和以外的所有字节都需要计算
  */
static uint8_t PalmveinCom_CalcCheckSum(uint8_t *pData, uint16_t len)
{
	uint8_t sum = 0;
	//PALMVEIN_COM_TASK_DEBUG_LOG("check sum:");
	for (; len; len--)
	{
		//PALMVEIN_COM_TASK_DEBUG_LOG("%#2x ",*pData);
		sum ^= *pData++;
	}
	//PALMVEIN_COM_TASK_DEBUG_LOG("\r\n");
	return sum;
}


/**
  * @brief  加载待发送的数据
  * @note   将要发出的数据，填入发送缓存区
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus PalmveinCom_LoadingDataToBeSent(uint8_t *pData, uint16_t len)
{
	if (len > 0x7FFF) //直接发
	{
		len &= 0x7FFF;
		PalmveinCom_PrintfTxData(pData, len);
		Device_Write(VHW_UART_PALMVEIN, pData, len, 0);
		return SUCCESS;
	}
	return ERROR;
}


/**
  * @brief  掌静脉模块 数据打包
  * @note   
  *
  * @param  cmd：消息id
  * @param  pData：数据
  * @param  dataLen：数据长度
  * @param  waitAckFlag：等待回复标志
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus PalmveinCom_SendPacket(uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag)
{
    CmdPacket_stu_t *pCmdPacket = (CmdPacket_stu_t *)CmdPacketTxInfo.dataBuf;
    ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)CmdPacketTxInfo.dataBuf; //加密模式帧头数据结构
	uint8_t encryptData[64] = {0};
	uint16_t encryptDataLen;
	uint16_t encryptInputLen;
    ErrorStatus re;

    //memset(&CmdPacketTxInfo,0,sizeof(CmdPacketTxInfo));
    CmdPacketTxInfo.cmd = cmd;
	CmdPacketTxInfo.waitAckFlag = waitAckFlag;
	CmdPacketTxInfo.cnt = 1;
	CmdPacketTxInfo.status = TX_STA_WAIT_ACK;
	CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();

    //数据打包
    pCmdPacket->head.stx = PROTOCOL_STX;
	pCmdPacket->head.stx = SWAP16(pCmdPacket->head.stx); //大小端转化
	pCmdPacket->head.msgID = cmd;
	pCmdPacket->head.len = dataLen;						 //data长度
	pCmdPacket->head.len = SWAP16(pCmdPacket->head.len); //大小端转化
	memcpy(pCmdPacket->data, pData, dataLen);

    //PALMVEIN_COM_TASK_LOG("tx cmd: %x,len: %d",cmd,dataLen);

    pCmdPacket->data[dataLen] = PalmveinCom_CalcCheckSum((uint8_t *)&(pCmdPacket->head.stx) + CHECK_SUM_DATA_START, dataLen + CHECK_SUN_LEN_ADD);
	CmdPacketTxInfo.dataLen = sizeof(CmdPacket_stu_t) + dataLen + 1;

    //开启OTA指令需要加密
    if(1 == PalmveinEncrypt_Get_EnFlag())
    {
        PALMVEIN_COM_TASK_LOG("encrypt packet: %d",strlen(CmdPacketTxInfo.dataBuf));

        CmdPacketTxInfo.dataLen = dataLen + 5;
		PalmveinCom_PrintfTxData(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen); //仿真模式打印出加密前的数据
																			 //#endif
		pPacketHeadEncrypt->stx = PROTOCOL_STX;
		pPacketHeadEncrypt->stx = SWAP16(pPacketHeadEncrypt->stx); //大小端转化
		encryptInputLen = dataLen + 3;      //数据内容 + msgid(1) + len(2)

        //数据加密
		PalmveinEncrypt_Decrypt(1, (uint8_t *)&pCmdPacket->head.msgID, &encryptInputLen, encryptData, &encryptDataLen);

		memcpy(pPacketHeadEncrypt->data, encryptData, encryptDataLen);  //加密数据赋值
		pPacketHeadEncrypt->len = encryptDataLen;

		pPacketHeadEncrypt->data[encryptDataLen] = PalmveinCom_CalcCheckSum((uint8_t *)pPacketHeadEncrypt->data, encryptDataLen);
		CmdPacketTxInfo.dataLen = sizeof(ProtocolDataHeadEncrypt_stu_t) + encryptDataLen + 1;
		pPacketHeadEncrypt->len = SWAP16(pPacketHeadEncrypt->len); //大小端转化

    }

    //发送数据
    re = PalmveinCom_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
    // PALMVEIN_COM_TASK_LOG("tx status: %d",CmdPacketTxInfo.status);

	if (cmd == MID_INIT_ENCRYPTION)
	{
		PalmveinEncrypt_Set_EnFlag(1); //启动加密通信
	}
	else if (cmd == MID_START_OTA)
	{
		PalmveinEncrypt_Set_EnFlag(0); //关闭加密通信
	}

    return re;
}

ErrorStatus PalmveinCom_OTASendPacket(uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag)
{
	CmdPacketTxInfo.waitAckTimeout = 300;  //300ms超时
	return PalmveinCom_SendPacket(cmd,pData,dataLen,waitAckFlag);
}

/**
  * @brief  掌静脉模组发送数据写入队列 H->M
  * @note   调用此函数时不是立马发送，而是暂存到环形缓存里面
  * @param  pData:发送数据
  */
void PalmveinCom_TxCmdRingBuffWrite(Palmvein_P_TxCmdMsg_stu_t *pData)
{
	if (palmveinTx_rbHandle != NULL)
	{
		OSAL_RingBufferWrite(palmveinTx_rbHandle, pData);
	}
}

/**
  * @brief  当前掌静脉模组模式
  * @note
  */
static PalmVein_mode_enum_t PalmveinCom_Get_PalmveinModule_CurMode(void)
{
	return palmveinModuleStatus.curMode;
}

/**
  * @brief  处理掌静脉发送和设置缓存数据，读取缓存队列的数据发送
  *
  * @note  
  */
void PalmveinCom_SendMsgProcess(void)
{
	if (OSAL_RingBufferGetValidSize(palmveinTx_rbHandle) != 0)
	{
		FlagStatus ackFlag;
		Palmvein_P_TxCmdMsg_stu_t Data = {0};
		OSAL_RingBufferRead_No_Clear(palmveinTx_rbHandle, &Data);

		if ((Data.msgID == MID_RESET && PALMVEIN_MODULE_SLEEPED_MODE != PalmveinCom_Get_PalmveinModule_CurMode())
				|| (CmdPacketTxInfo.status == TX_STA_IDLE)) // 在非休眠状态下发重置命令立即执行,或者在发送空闲时执行
		{

			if (OSAL_RingBufferRead(palmveinTx_rbHandle, &Data) == SUCCESS)
			{
				if (Data.cb != NULL)
				{
					ackFlag = SET;
					//指令对应回复的回调进行赋值
					pCmdCallback = Data.cb;
					CmdPacketTxInfo.waitAckTimeout = Data.timeout;
				}
				else
				{
					ackFlag = RESET;
				}
				PalmveinCom_SendPacket(Data.msgID, Data.dataBuf, Data.data_len, ackFlag);
				PALMVEIN_COM_TASK_LOG(C_LIGHT_GREEN C_COLOR "CMD_Tx_OK msgID = 0X%2X\r\n" C_NONE, Data.msgID);
			}
		}
	}

}

/**
  * @brief  掌静脉数据快速直接发送
  *
  * @note  
  */
void PalmveinCom_FastSendMsg(Palmvein_P_TxCmdMsg_stu_t *pData)
{
	FlagStatus ackFlag;
	Palmvein_P_TxCmdMsg_stu_t Data = {0};

	// memcpy(&Data,pData,sizeof(Palmvein_P_TxCmdMsg_stu_t));

	if (pData->cb != NULL)
	{
		
		ackFlag = SET;
		//指令对应回复的回调进行赋值
		pCmdCallback = pData->cb;
		CmdPacketTxInfo.waitAckTimeout = pData->timeout;
		
	}
	else
	{
		ackFlag = RESET;
	}
	PalmveinCom_SendPacket(pData->msgID, pData->dataBuf, pData->data_len, ackFlag);
	PALMVEIN_COM_TASK_LOG(C_LIGHT_GREEN C_COLOR "Fast CMD_Tx_OK msgID = 0X%2X\r\n" C_NONE, pData->msgID);	
}


/***********************************发送操作相关函数 END**************************************************/
/********************************************************************************************************/

/**
  * @brief  从底层环形缓存获取一包数据并解析
  *
  * @note   底层驱动收到数据，会暂存在环形缓存区
  *
  * @return 返回解析后的数据包地址，解析失败返回NULL
  */
static uint8_t *PalmveinCom_GetOnePacket(void)
{
	static uint8_t getPacketTimeoutCnt = 0;
    uint8_t *protocolBuff = NULL;               //解析的buff
    uint8_t *pCnt = NULL;                       
	uint8_t sum = 0;
	uint16_t packetLen = 0;                     //整包长度
	uint8_t tmpData;                            //缓冲变量，从缓冲区读数据
	uint32_t tmpLen = 0;
    ProtocolDataHead_stu_t *pPacketHead = NULL;
    ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = NULL; //加密模式帧头数据结构

	uint8_t decryptData[MAX_RX_PACKAGE_LEN] = {0};
    uint8_t buff[64];
	uint16_t decryptDataLen;

    //查询缓冲区是否有数据
	tmpLen = OSAL_RingBufferGetValidSize(palmveinRx_rbHandle);
	if (tmpLen == 0)
	{
		/* 连续5次没有读取到数据（50ms） */
		if (++getPacketTimeoutCnt >= 5)
		{
			if(CmdPacketRxInfo.protocolCount)
			{
				PALMVEIN_COM_TASK_LOG("palmvein recv timeout,len %d\r\n",CmdPacketRxInfo.protocolCount);
			}
			getPacketTimeoutCnt = 0;
			CmdPacketRxInfo.protocolCount = 0; //清0解析计数
		}

		if(CmdPacketRxInfo.protocolCount)
		{	
			PALMVEIN_COM_TASK_LOG("pack timeout cnt:%d",getPacketTimeoutCnt);
		}
		return NULL;
	}
	getPacketTimeoutCnt = 0;

    PALMVEIN_COM_TASK_LOG("palmvein get pack len:%d",tmpLen);
    pCnt = &(CmdPacketRxInfo.protocolCount);	//解析计数
    protocolBuff = CmdPacketRxInfo.protocolBuf; //解析缓存
    pPacketHead = (ProtocolDataHead_stu_t *)protocolBuff;
    pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)protocolBuff;
    //循环读字节
    for (; tmpLen; tmpLen--)
	{
		OSAL_RingBufferRead(palmveinRx_rbHandle, &tmpData); //读取到一个字节数据
        //PALMVEIN_COM_TASK_LOG("tmpdata %02x\r\n",tmpData);
        if(*pCnt == 0)
        {
            if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
            {
                protocolBuff[0] = tmpData;
                // PALMVEIN_COM_TASK_LOG("PROTOCOL_STX head ok");
                //PALMVEIN_COM_TASK_LOG(" %02X", protocolBuff[*pCnt]);
                *pCnt = 1;
                
            }
        }
        else if(*pCnt == 1)
        {
            if (tmpData == (PROTOCOL_STX & 0x00FF)) //帧数据头低字节
			{
				protocolBuff[1] = tmpData;
                //PALMVEIN_COM_TASK_LOG(" %02X", protocolBuff[*pCnt]);
				*pCnt = 2;
			}
            else if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
			{


            }
            else
            {
                *pCnt = 0;
            }
        }
        else if(*pCnt > 1)
        {
            protocolBuff[*pCnt] = tmpData;
            *pCnt = *pCnt + 1;
            //PALMVEIN_COM_TASK_LOG("%02X", protocolBuff[*pCnt]);
            //非加密
            if(PalmveinEncrypt_Get_EnFlag() == 0)
            {
                if(*pCnt == 5)
                {
                    // PALMVEIN_COM_TASK_LOG("1 len %04x, %04x", pPacketHead->len,pPacketHead->stx);
                    pPacketHead->len = SWAP16(pPacketHead->len); //大小端转化
					pPacketHead->stx = SWAP16(pPacketHead->stx); //大小端转化
                    PALMVEIN_COM_TASK_LOG("rx len %04x, %04x", pPacketHead->len,pPacketHead->stx);
                }
                else if(*pCnt > 5)
                {
                    packetLen = pPacketHead->len + 6;  //包总长，data + 包头(2) + msgid(1) + datalen(2) + checksum(1)
                    if(packetLen == *pCnt)
                    {
                        sum = PalmveinCom_CalcCheckSum(protocolBuff + CHECK_SUM_DATA_START, pPacketHead->len + CHECK_SUN_LEN_ADD);

                        if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
						{
                            PALMVEIN_COM_TASK_LOG("RECEIVE RIGHT:");
                            for (int i = 0; i < packetLen; i++)
                            {
                                __PALMVEIN_COM_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
                            }
                            __PALMVEIN_COM_TASK_DEBUG_LOG("\r\n");
                            *pCnt = 0;
                            return protocolBuff;
                        }
                        else
                        {
                            PALMVEIN_COM_TASK_LOG("CRC ERR:");
                            for (int i = 0; i < packetLen; i++)
                            {
                                __PALMVEIN_COM_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
                            }
                            __PALMVEIN_COM_TASK_DEBUG_LOG("\r\n");
                        }
                        
                        *pCnt = 0;
                        return NULL;
                        
                    }
                    else
                    {
                        //PALMVEIN_COM_TASK_LOG("packetLen: %02x,%02x",*pCnt,packetLen);
                    }
                }
            }
            else
            {
                if (*pCnt == 4)
				{
                    // PALMVEIN_COM_TASK_LOG("1 encrypt len: %02x",pPacketHeadEncrypt->len);
					pPacketHeadEncrypt->len = SWAP16(pPacketHeadEncrypt->len); //大小端转化
					pPacketHeadEncrypt->stx = SWAP16(pPacketHeadEncrypt->stx); //大小端转化
                    //PALMVEIN_COM_TASK_LOG("rx encrypt len: %02x",pPacketHeadEncrypt->len);
				}
				if (*pCnt > 4)
				{
					packetLen = pPacketHeadEncrypt->len + 5;
					if (*pCnt >= MAX_RX_PACKAGE_LEN || packetLen == *pCnt)
					{
						if (packetLen == *pCnt)
						{
							sum = PalmveinCom_CalcCheckSum(pPacketHeadEncrypt->data, pPacketHeadEncrypt->len);
							if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
							{
                                uint16_t inputlen = pPacketHeadEncrypt->len;
								PalmveinEncrypt_Decrypt(0, pPacketHeadEncrypt->data, &inputlen, decryptData, &decryptDataLen);
								memcpy(&pPacketHeadEncrypt->len, decryptData, decryptDataLen);
								pPacketHead->len = SWAP16(pPacketHead->len); //大小端转化
								PALMVEIN_COM_TASK_LOG("RECEIVE RIGHT: %02x",pPacketHead->len);
								for (int i = 0; i < packetLen; i++)
								{
									__PALMVEIN_COM_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__PALMVEIN_COM_TASK_DEBUG_LOG("\r\n");
								*pCnt = 0;

								if ((pPacketHead->len + 6) <= MAX_RX_PACKAGE_LEN)
								{
									return protocolBuff;
								}
								else
								{
									PALMVEIN_COM_TASK_LOG("LEN ERR\r\n");
								}
							}
							else
							{
								PALMVEIN_COM_TASK_LOG("CRC ERR:");
								for (int i = 0; i < packetLen; i++)
								{
									__PALMVEIN_COM_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__PALMVEIN_COM_TASK_DEBUG_LOG("\r\n");
							}
						}
						else
						{
							PALMVEIN_COM_TASK_LOG("packet err\r\n");
						}
						*pCnt = 0;
						return NULL;
					}
                    else
                    {
                        //PALMVEIN_LOG("packetLen: %02x,%02x",*pCnt,packetLen);
                    }
				}
            }

        }

    }
	
	return NULL;
}


/**
  * @brief  重发指令包
  *
  * @note   
  */
static void PalmveinCom_ResendCmdPacket(void)
{
	uint32_t currentTime = OSAL_GetTickCount();
	uint8_t ret = ACK_RES_TIMEOUT;
	Palmvein_DealParam_stu_t DealParam;

	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK) //当前状态正在等应答
	{
		if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
		{
			//ERR:超时
			PALMVEIN_COM_TASK_LOG("wait ack Time out cmd = %#2x,%#2x,%#2x,%#2x", CmdPacketTxInfo.cmd, currentTime, CmdPacketTxInfo.timeStamp, CmdPacketTxInfo.waitAckTimeout);
            CmdPacketTxInfo.cnt++;

			PALMVEIN_COM_TASK_LOG("cmd %2x\r\n",CmdPacketTxInfo.cmd);

			if(CmdPacketTxInfo.cmd == MID_ENROLL)
			{
				pCmdCallback(ret, NULL, 0);
				pCmdCallback = NULL;
				CmdPacketTxInfo.status = TX_STA_IDLE;
				return ;
			}

			if(CmdPacketTxInfo.cnt <= 2)	//重发一次
			{
				CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
				PalmveinCom_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
				return ;
			}

			/*重发一次依然没有收到回复*/
			if (pCmdCallback != NULL)
			{
				//各指令的对应reply的回调函数进行处理
				pCmdCallback(ret, NULL, 0);
				pCmdCallback = NULL;
			}
			CmdPacketTxInfo.status = TX_STA_IDLE;

			if(CmdPacketTxInfo.cmd == MID_OTA_PACKET)
			{
				Palmvein_P_OtaPack_Callback(ret,NULL,0);
			}
		}

	}

}


/**
  * @brief  处理应答reply包结果
  * @note
  *
  * @param  pAckPacket：包内容
  */
static void PalmveinCom_Reply_PacketResult(CmdPacket_stu_t *pAckPacket)
{
	Reply_data_stu_t *replyData = (Reply_data_stu_t *)pAckPacket->data;

	if (replyData->r_msgID == CmdPacketTxInfo.cmd)
	{
		PALMVEIN_COM_TASK_LOG(C_YELLOW C_COLOR "Callback CMD=%#2X\r\n" C_NONE, replyData->r_msgID);

		if (pCmdCallback != NULL)
		{
			//各指令的对应reply的回调函数进行处理
			pCmdCallback(replyData->result, replyData->r_data, pAckPacket->head.len - 2);
			if(replyData->r_msgID != MID_ENROLL)
			{
				pCmdCallback = NULL;
			}
			
		}
		CmdPacketTxInfo.status = TX_STA_IDLE;
	}

	if(CmdPacketTxInfo.cmd == MID_OTA_PACKET)
	{
		Palmvein_P_OtaPack_Callback(replyData->result,replyData->r_data, pAckPacket->head.len - 2);
	}
}

/**
  * @brief  处理note包的结果
  * @note   模块的状态包括：IDLE(0),BUSY(1),ERROR(2),INVALID(3) OTA进行中(4)
  *
  * @param  pCmdPacket: 包数据
  */
static void PalmveinCom_Note_PacketResult(CmdPacket_stu_t *pCmdPacket)
{
	Note_data_stu_t *noteData = (Note_data_stu_t *)pCmdPacket->data;

	switch (noteData->n_msgID)
	{
			//开机准备好了
		case NID_READY:
			palmveinModuleStatus.timeout = FOREVER_TIME_OUT;
			Palmvein_P_Nid_Ready();
			break;

			//掌静脉信息返回
		case NID_PALMVEIN_STATE:
			Palmvein_P_Nid_Palmvein_Status(noteData->n_data);
			break;

			//OTA结果
		case NID_OTA_DONE:
			Palmvein_P_Nid_Ota_Done(noteData->n_data);
			break;
		
		default:
			break;
	}

}

/**
  * @brief  解析读取的数据包
  * @note
  *
  * @param  pData:数据包
  */
static void PalmveinCom_ParseRxPacket(uint8_t *pData)
{
	CmdPacket_stu_t *pPacketHead = (CmdPacket_stu_t *)pData;

    if (pPacketHead->head.msgID == MID_REPLY) //处理reply消息
    {
        PALMVEIN_COM_TASK_LOG("reply pack");
        PalmveinCom_Reply_PacketResult((CmdPacket_stu_t *)pData);
        
    }

    else if (pPacketHead->head.msgID == MID_NOTE) //处理note消息
    {
        PALMVEIN_COM_TASK_LOG("note pack");
        PalmveinCom_Note_PacketResult((CmdPacket_stu_t *)pData);
        
    }
    
}



/**
  * @brief  接收数据并解析处理
  *
  * @note   先接收数据再解析数据，如果接收到note包需要发送ack包
  */
void PalmveinCom_RecvMsgProcess(void)
{

	uint8_t *pData = NULL;
	pData = PalmveinCom_GetOnePacket(); //得到一包数据并检验校验和

    if (pData != NULL)
	{
		palmvein_err_process(0);
		PalmveinCom_ParseRxPacket(pData); //解析数据
	}

	PalmveinCom_ResendCmdPacket();		 //超时重发命令包
}



/**
  * @brief 创建数据读取缓冲区队列
  *
  * @note 
  */
static void PalmveinCom_CreateRingBuffHandle(void)
{
	static FlagStatus firstPowerOn = SET;
	if (firstPowerOn == SET)
	{
        /*发送指令队列*/
		palmveinTx_rbHandle = OSAL_RingBufferCreate(PALMVEIN_TX_CMD_BUFF_NUM, sizeof(Palmvein_P_TxCmdMsg_stu_t));
		if (palmveinRx_rbHandle == NULL)
		{
			palmveinRx_rbHandle = OSAL_RingBufferCreate(500, 1);
		}
		firstPowerOn = RESET;
	}
}

//掌静脉串口回调函数
static void PalmveinCom_ReceiveCb(VirtualHardware_enum_t dev, void *data, uint32_t len)
{
	if (palmveinRx_rbHandle == NULL)
	{
		return;
	}
	for (uint32_t i = 0; i < len; i++)
	{
		uint8_t tmp = ((uint8_t *)data)[i];
		// printf("%02X",tmp);

		if (OSAL_RingBufferWrite(palmveinRx_rbHandle, &tmp) != SUCCESS)
		{
			PALMVEIN_COM_TASK_LOG("palmvein ringbuff write err\r\n");
			return;
		}

	}
}


/**
  * @brief 清除掌静脉发送和设置缓存数据
  *
  * @note  
  */
static void PalmveinCom_ResetRingBuff(void)
{
	OSAL_RingBufferReset(palmveinTx_rbHandle);
	OSAL_RingBufferReset(palmveinRx_rbHandle);
}



void PalmveinCom_Init(void)
{
    PalmveinCom_CreateRingBuffHandle();
    Device_RegisteredCB(VHW_UART_PALMVEIN, PalmveinCom_ReceiveCb);
	CmdPacketTxInfo.status = TX_STA_IDLE;

}



/**
  * @brief  掌静脉模组上电
  * @note
  */
void Palmvein_PowerOn_DealFun(void)
{
	
	PALMVEIN_MODULE_POWER_ON;
    Device_Enable(VHW_UART_PALMVEIN);
    PalmveinEncrypt_Set_EnFlag(0); //非加密通信
    palmveinModuleStatus.curStatus = PALMVEIN_STATUS_POWER_ON;
    palmveinModuleStatus.start_time = OSAL_GetTickCount();
	palmveinModuleStatus.timeout = PALMVEIN_POWER_ON_TIMEOUT;
	PALMVEIN_COM_TASK_LOG("palmvein module power on");

}

/**
  * @brief  掌静脉模组下电
  * @note
  */
void Palmvein_PowerDown_DealFun(void)
{
	PALMVEIN_MODULE_POWER_OFF;
	CmdPacketTxInfo.status = TX_STA_IDLE;
    Device_Disable(VHW_UART_PALMVEIN);
	palmveinModuleStatus.curStatus = PALMVEIN_STATUS_POWER_DOWN;
	PALMVEIN_COM_TASK_LOG("palmvein module power off");
	OSAL_RingBufferReset(palmveinTx_rbHandle);
    PalmVeinMsg_t palmveinMsg;
	palmveinMsg.action = PALMVEIN_ACTION_POWER_OFF;
	palmveinMsg.id = 0;
	OSAL_MessagePublish(&palmveinMsg, sizeof(palmveinMsg));
}

/**
  * @brief  掌静脉睡眠处理
  * @note
  */
void PalmveinCom_SleepProcess(void)
{
	CmdPacketTxInfo.status = TX_STA_IDLE;
	palmveinModuleStatus.curStatus = PALMVEIN_STATUS_POWER_DOWN;
    PalmveinCom_ResetRingBuff();
    Device_Disable(VHW_UART_PALMVEIN);
	PALMVEIN_MODULE_POWER_OFF;
}

/**
  * @brief  掌静脉获取当前发送状态
  * @note
  */
uint8_t PalmveinCom_Get_TxStatus(void)
{
	// printf("CmdPacketTxInfo.status %d\r\n",CmdPacketTxInfo.status);
	return CmdPacketTxInfo.status;
}	